/**
 * @file         bsc_can_plug.h
 * @brief        CAN服务框架 ———— 插件类
 * @note         用户自定义插件接口函数的具体实现，为插件列表提供固定的插件接口集
 * @author       Jpz(puzhao.jin@hopechart.com, 靳普诏)
 * @data         2022-8-10
 * @version      1.0
 *
 * @par          修改日志
 * <table>
 * <tr><th>Date        <th>Version               <th>Author          <th>Description
 * <tr><td>2022-8-10   <td>1.0                   <td>Jpz             <td>创建初始版本
 * @copyright    杭州鸿泉物联网技术股份有限公司
 */


#ifndef _BSC_CAN_PLUG_IF_H_
#define _BSC_CAN_PLUG_IF_H_

#include "ofc/ofc_types.h"
#include "bsc_can_server/bsc_can_device.h"
#include "bsc_can_server/bsc_can_server_if.h"

#ifdef __cplusplus
extern "C" {
#endif




// ~~~~~~~~~~~~~~~ 插件接口 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


/**
 * 插件初始化接口， 当插件列表注册到服务中时会依次调用插件（Methods(server_if, method_no, user_params) 此时metiod_no == kBsCanPlugMethodIdInit）
 * @param *server_if    服务框架提供can服务接口（@ref IBsCanServerIf）
 * @param *user_params  用户在构建插件时的传参地址，可以为NULL
 * @return >= 0 成功；
 *         <  0 失败；
 *         返回值对服务框架无影响，在此仅作日志输出的依据（暂未添加日志功能）
 */
typedef Int32 (*IBsCanPlugIfDoInit)(IBsCanServerIf *server_if, void *user_params);

/**
 * 插件反初始化接口， 当插件列表注销时会依次调用插件（Methods(server_if, method_no, user_params) 此时metiod_no == kBsCanPlugMethodIdDone）
 * @param *server_if    服务框架提供can服务接口（@ref IBsCanServerIf）
 * @param *user_params  用户在构建插件时的传参地址，可以为NULL
 * @return >= 0 成功；
 *         <  0 失败；
 *         返回值对服务框架无影响，在此仅作日志输出的依据（暂未添加日志功能）
 */
typedef Int32 (*IBsCanPlugIfDoDone)(IBsCanServerIf *server_if, void *user_params);


/**
 * 接收来自can服务的数据帧推送  
 * @param *server_if    服务框架提供can服务接口（@ref IBsCanServerIf）
 * @param *user_params  用户在构建插件时的传参地址，可以为NULL
 * @param *can_data     当前推送的 1 帧 CAN 数据
 * @return 
 */
typedef void (*IBsCanPlugIfDoReceive)(IBsCanServerIf *server_if, void *user_params, TBsCanData *can_data);

/**
 * 插件周期调度接口
 * @param *server_if    服务框架提供can服务接口（@ref IBsCanServerIf）
 * @param *user_params  用户在构建插件时的传参地址，可以为NULL
 * @param cur_ticks     被调度时的 tick 值
 * @return 调度的周期tick值
 */
typedef UInt32 (*IBsCanPlugIfDoScheduler)(IBsCanServerIf *server_if, void *user_params, UInt32 cur_ticks);

/**
 * 过滤器，用来判断当前canid是否允许分发给当前插件
 * @param *server_if    服务框架提供can服务接口（@ref IBsCanServerIf）
 * @param *user_params  用户在构建插件时的传参地址，可以为NULL
 * @param can_id        当前接收到的消息的消息id
 * @return True 允许当前消息推送给插件  False 丢弃当前消息
 */
typedef Bool (*IBsCanPlugIfDoFilter)(IBsCanServerIf *server_if, void *user_params, UInt32 can_id);


enum IBsCanPlugIfMethodIdTag
{
    kBsCanPlugMethodIdInit         = 0,     ///< 插件初始化接口
    kBsCanPlugMethodIdDone         = 1,     ///< 插件反初始化接口
};

/**
 * 插件接口集入口 
 * @param *server_if    服务框架提供can服务接口（@ref IBsCanServerIf）
 * @param method_no     方法编号 （@ref enum IBsCanPlugIfMethodIdTag）
 * @param *user_params  用户在构建插件时的传参地址，可以为NULL
 * @return 返回对应功能函数返回值
 */
typedef Int32 (*IBsCanPlugIfDoMethods)(void *server_if, UInt32 method_no, void *user_params);

// 插件接口集
typedef struct IBsCanPlugIfTag IBsCanPlugIf;
struct IBsCanPlugIfTag
{
    IBsCanPlugIfDoMethods   Methods;        ///< 插件初始化接口(用户提供的)
    IBsCanPlugIfDoFilter    OnFilter;       ///< 过滤
    IBsCanPlugIfDoReceive   OnRecv;         ///< 接收到推送的数据帧
    IBsCanPlugIfDoScheduler RunOnce;        ///< 执行一次被调度
};



// ~~~~~~~~~~~~~~~~~~ 组件调用 ~~~~~~~~~~~~~~~~~~~~~~~~

Int32 IBsCanPlugIfInit(IBsCanPlugIf *self, IBsCanServerIf *server_if, void *user_params);
Int32 IBsCanPlugIfDone(IBsCanPlugIf *self, IBsCanServerIf *server_if, void *user_params);

Bool IBsCanPlugIfFilter(IBsCanPlugIf *self, IBsCanServerIf *server_if, void *user_params, UInt32 can_id);
void IBsCanPlugIfReceive(IBsCanPlugIf *self, IBsCanServerIf *server_if, void *user_params, TBsCanData *can_data);
UInt32 IBsCanPlugIfScheduler(IBsCanPlugIf *self, IBsCanServerIf *server_if, void *user_params, UInt32 cur_ticks);



#ifdef __cplusplus
} // extern "C" {
#endif


#endif // #ifndef _BSC_CAN_PLUG_IF_H_

